# -*- coding:utf-8 -*-

import websocket
import datetime
import hashlib
import base64
import hmac
import json
from urllib.parse import urlencode
import time
import ssl
from wsgiref.handlers import format_date_time
from time import mktime
import os
import wave
import threading

class Ws_Param:
    def __init__(self, APPID, APIKey, APISecret, Text):
        self.APPID = APPID
        self.APIKey = APIKey
        self.APISecret = APISecret
        self.Text = Text

        # 公共参数
        self.CommonArgs = {"app_id": self.APPID, "status": 2}

        # 业务参数
        self.BusinessArgs = {
            "tts": {
                "vcn": "x4_lingxiaoxuan_oral",  # 发音人参数
                "volume": 50,
                "speed": 50,
                "pitch": 50,
                "audio": {
                    "encoding": "raw",  # PCM 格式
                    "sample_rate": 24000,
                    "channels": 1,
                    "bit_depth": 16,
                }
            }
        }

        # 数据参数
        self.Data = {
            "text": {
                "encoding": "utf8",
                "compress": "raw",
                "format": "plain",
                "status": 2,
                "seq": 0,
                "text": base64.b64encode(self.Text.encode('utf-8')).decode("utf8"),
            }
        }


def assemble_ws_auth_url(request_url, method="GET", api_key="", api_secret=""):
    """生成带有签名的 WebSocket URL"""
    stidx = request_url.index("://")
    host = request_url[stidx + 3:]
    schema = request_url[:stidx + 3]
    edidx = host.index("/")
    host, path = host[:edidx], host[edidx:]

    now = datetime.datetime.now()
    date = format_date_time(mktime(now.timetuple()))
    signature_origin = f"host: {host}\ndate: {date}\n{method} {path} HTTP/1.1"
    signature_sha = hmac.new(
        api_secret.encode('utf-8'),
        signature_origin.encode('utf-8'),
        digestmod=hashlib.sha256
    ).digest()
    signature_sha = base64.b64encode(signature_sha).decode('utf-8')

    authorization_origin = f'api_key="{api_key}", algorithm="hmac-sha256", headers="host date request-line", signature="{signature_sha}"'
    authorization = base64.b64encode(authorization_origin.encode('utf-8')).decode('utf-8')

    values = {"host": host, "date": date, "authorization": authorization}
    return f"{request_url}?{urlencode(values)}"


def pcm_to_wav(pcm_file, wav_file, channels=1, bits=16, sample_rate=24000):
    """将 PCM 文件转换为 WAV 格式"""
    with open(pcm_file, 'rb') as pcm_f:
        pcm_data = pcm_f.read()
    with wave.open(wav_file, 'wb') as wav_f:
        wav_f.setnchannels(channels)
        wav_f.setsampwidth(bits // 8)
        wav_f.setframerate(sample_rate)
        wav_f.writeframes(pcm_data)


def on_message(ws, message, output_pcm_path):
    """处理 WebSocket 接收到的消息"""
    try:
        message = json.loads(message)
        code = message["header"]["code"]
        if "payload" in message:
            audio = base64.b64decode(message["payload"]["audio"]["audio"])
            status = message["payload"]["audio"]["status"]
            with open(output_pcm_path, 'ab') as f:
                f.write(audio)
            if status == 2:
                ws.close()
        if code != 0:
            print(f"Error: {message['message']}, Code: {code}")
    except Exception as e:
        print("Error processing message:", e)


def on_error(ws, error):
    """处理 WebSocket 错误"""
    print("WebSocket Error:", error)


def on_close(ws, *_):
    """处理 WebSocket 关闭"""
    print("WebSocket closed")


def on_open(ws):
    """发送数据"""
    def run():
        d = {
            "header": wsParam.CommonArgs,
            "parameter": wsParam.BusinessArgs,
            "payload": wsParam.Data,
        }
        ws.send(json.dumps(d))
    threading.Thread(target=run).start()


def text2wav(text, output_pcm_path, output_wav_path):
    """文本转语音主函数"""
    global wsParam
    appid = "9cb17a59"
    apisecret = "YWVlYTM5OWJlNWRlNmYzMWFjYmMwMTRk"
    apikey = "1d1098cd6e6c69adb3969edcf2aa32eb"
    wsParam = Ws_Param(APPID=appid, APISecret=apisecret, APIKey=apikey, Text=text)

    req_url = "wss://cbm01.cn-huabei-1.xf-yun.com/v1/private/mcd9m97e6"
    ws_url = assemble_ws_auth_url(req_url, "GET", apikey, apisecret)

    websocket.enableTrace(False)
    ws = websocket.WebSocketApp(
        ws_url,
        on_message=lambda ws, msg: on_message(ws, msg, output_pcm_path),
        on_error=on_error,
        on_close=on_close
    )
    ws.on_open = on_open
    ws.run_forever(sslopt={"cert_reqs": ssl.CERT_NONE})

    # 转换 PCM 为 WAV
    pcm_to_wav(output_pcm_path, output_wav_path)


if __name__ == "__main__":
    text2wav("回应我吧，爱莉希雅！", "./test.pcm", "./test.wav")
    print("Text-to-Speech synthesis completed.")
